﻿using System;
using System.IO;
using System.Text;
using System.Web.Configuration;
using System.Web.Services.Protocols;
using MailPriority = System.Net.Mail.MailPriority;
using System.Configuration;

namespace CustomException
{
    public class ExceptionUtils
    {
        #region Attributes

        private static readonly bool IsLoggable = Convert.ToBoolean(ConfigurationManager.AppSettings["GENERATE_LOGS"] ?? WebConfigurationManager.AppSettings["GENERATE_LOGS"] ?? "false");
        private static readonly bool SendLogMail = Convert.ToBoolean(ConfigurationManager.AppSettings["SEND_LOG_MAIL"] ?? WebConfigurationManager.AppSettings["SEND_LOG_MAIL"] ?? "false");

        private static readonly string LogsDirPath = string.Format("{0}logs", AppDomain.CurrentDomain.BaseDirectory);
        private static readonly string LogsFilePath = string.Format("{0}logs{1}{2:dd-MM-yyyy}.log",
                                                            AppDomain.CurrentDomain.BaseDirectory,
                                                            Path.DirectorySeparatorChar,
                                                            DateTime.Now);
        #endregion

        #region Private Methods

        private static bool DirectoryOk
        {
            get
            {
                bool ok;

                if (Directory.Exists(LogsDirPath))
                {
                    File.SetAttributes(LogsDirPath, FileAttributes.Normal);
                    ok = true;
                }
                else
                {
                    try
                    {
                        Directory.CreateDirectory(LogsDirPath);
                        File.SetAttributes(LogsDirPath, FileAttributes.Normal);
                        ok = true;
                    }
                    catch
                    {
                        ok = false;
                    }
                }

                return ok;
            }
        }

        private static void SendEmail(ref string message)
        {
            try
            {
                if (SendLogMail)
                {
                    EmailUtility.SendEmail((ConfigurationManager.AppSettings["SMTP"] ?? WebConfigurationManager.AppSettings["SMTP"]),
                                           Convert.ToInt32((ConfigurationManager.AppSettings["SMTP_PORTA"] ?? WebConfigurationManager.AppSettings["SMTP_PORTA"])),
                                           (ConfigurationManager.AppSettings["EMAIL_AUTHENTICATED_USER"] ?? WebConfigurationManager.AppSettings["EMAIL_AUTHENTICATED_USER"]),
                                           (ConfigurationManager.AppSettings["EMAIL_GRUPO_RECEBER"] ?? WebConfigurationManager.AppSettings["EMAIL_GRUPO_RECEBER"]),
                                           (ConfigurationManager.AppSettings["SEND_LOG_MAIL_TITLE"] ?? WebConfigurationManager.AppSettings["SEND_LOG_MAIL_TITLE"]),
                                           message,
                                           MailPriority.High,
                                           null,
                                           (ConfigurationManager.AppSettings["EMAIL_AUTHENTICATED_USER"] ?? WebConfigurationManager.AppSettings["EMAIL_AUTHENTICATED_USER"]),
                                           (ConfigurationManager.AppSettings["SENHA_AUTHENTICATED_USER"] ?? WebConfigurationManager.AppSettings["SENHA_AUTHENTICATED_USER"]),
                                           enableSsl: Convert.ToBoolean(ConfigurationManager.AppSettings["USE_SSL"] ?? WebConfigurationManager.AppSettings["USE_SSL"] ?? "false"));
                }
            }
            catch (Exception ex)
            {
                message += string.Concat(Environment.NewLine, "Erro ao enviar E-mail com o Log: ", ex.Message, Environment.NewLine, ex.StackTrace);
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Gera um arquivo de Logs padronizado para uma System.Exception ou SoapException
        /// </summary>
        /// <param name="ex">Objeto Exception</param>
        /// <param name="useInnerException">Se gerará o Log a partir da InnerException ou do próprio objeto Exception</param>
        public static void Log(System.Exception ex, bool useInnerException = true)
        {
            if (ex != null && IsLoggable && DirectoryOk)
            {
                try
                {
                    // Se deve gerar Logs pela InnerException
                    if (useInnerException
                        && !string.IsNullOrWhiteSpace(ex.InnerException.Message)
                        && !string.IsNullOrWhiteSpace(ex.InnerException.StackTrace))
                    {
                        var log = string.Format("{0}{1:hh:mm:ss} - {2}{0}{3}",
                                            Environment.NewLine,
                                            DateTime.Now,
                                            ex.InnerException.Message,
                                            ex.InnerException.StackTrace);

                        SendEmail(ref log);
                        File.AppendAllText(LogsFilePath, log, Encoding.Default);
                        File.SetAttributes(LogsFilePath, FileAttributes.Normal);
                    }

                    // Se deve gerar Logs pelo próprio objeto Exception 
                    else if (!useInnerException
                        && !string.IsNullOrWhiteSpace(ex.Message)
                        && !string.IsNullOrWhiteSpace(ex.StackTrace))
                    {
                        var log = string.Format("{0}{1:hh:mm:ss} - {2}{0}{3}",
                                            Environment.NewLine,
                                            DateTime.Now,
                                            ex.Message,
                                            ex.StackTrace);

                        SendEmail(ref log);
                        File.AppendAllText(LogsFilePath, log, Encoding.Default);
                        File.SetAttributes(LogsFilePath, FileAttributes.Normal);
                    }

                    // Se é uma SoapException
                    else if (ex is SoapException)
                    {
                        var soapEx = ex as SoapException;

                        if (!string.IsNullOrWhiteSpace(soapEx.Message)
                            && (soapEx.Detail != null)
                            && !string.IsNullOrWhiteSpace(soapEx.Detail.InnerText)
                            && !string.IsNullOrWhiteSpace(soapEx.StackTrace))
                        {
                            var log = string.Format("{0}{1:hh:mm:ss} - {2}{0}{3}{0}{4}",
                                                Environment.NewLine,
                                                DateTime.Now,
                                                soapEx.Message,
                                                soapEx.Detail.InnerText,
                                                soapEx.StackTrace);

                            SendEmail(ref log);
                            File.AppendAllText(LogsFilePath, log, Encoding.Default);
                            File.SetAttributes(LogsFilePath, FileAttributes.Normal);
                        }
                    }
                }
                catch { }
            }
        }

        #endregion
    }
}
